package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FundAccountFlowTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.AttrValuePojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.FormTitlePoJo;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataDeleteBatchDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataDeleteBatchVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.applist.pojo.AppListPojo;
import com.xbongbong.pro.applist.pojo.vo.ListAppVO;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.fundtransfer.pojo.FundTransferEditAttrUpdateDTO;
import com.xbongbong.pro.fundtransfer.pojo.FundTransferUpdateDTO;
import com.xbongbong.pro.fundtransfer.pojo.batch.FundTransferUpdateBatchDTO;
import com.xbongbong.pro.service.toolbox.statistic.help.FormHelp;
import com.xbongbong.saas.analytical.impl.FundTransferValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.FundAccountEntity;
import com.xbongbong.saas.domain.entity.FundAccountFlowEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.FundTransferEnum;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.model.FundAccountFlowModel;
import com.xbongbong.saas.model.FundAccountModel;
import com.xbongbong.saas.model.FundTransferModel;
import com.xbongbong.saas.service.FundTransferService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static java.lang.String.format;

/**
 * @author: 汪腾伟
 * @description： 调拨单service实现层
 * @date: Created in 2021/5/26 11:21
 */
@Service("fundTransferServiceImpl")
public class FundTransferServiceImpl implements FundTransferService {

    private static final Logger LOG = LoggerFactory.getLogger(FundTransferServiceImpl.class);

    @Resource
    private FundAccountModel fundAccountModel;
    @Resource
    private FundAccountFlowModel fundAccountFlowModel;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private FundTransferModel fundTransferModel;
    @Resource
    private FormHelp formHelp;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private LogHelp logHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private FundTransferValidateAnalyticalServiceImpl fundTransferAnalyticalService;
    @Resource
    private LogHandleHelp logHandleHelp;

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException{
        fundTransferAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 保存完之后需要进行的一些操作
     * (1)需要插入一条调拨单转出类型的流水以及一条调拨单转入类型的流水
     * (2)更新资金账户的里面的余额
     *
     * @param saasFormSaveDTO
     */
    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        String corpid = saasFormSaveDTO.getCorpid();
        PaasFormDataEntity paasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject data = paasFormDataEntity.getData();
        long nowTime = DateTimeUtil.getInt();
        String outAccountStr = data.getString(FundTransferEnum.OUT_FUND_ACCOUNT.getAttr());
        String inAccountStr = data.getString(FundTransferEnum.IN_FUND_ACCOUNT.getAttr());
        Long transferTime = data.getLongValue(FundTransferEnum.TRANSFER_TIME.getAttr());
        BigDecimal amount = data.getBigDecimal(FundTransferEnum.AMOUNT.getAttr());
        List<FundAccountFlowEntity> fundAccountFlowEntityList = new ArrayList<>();
        FundAccountFlowEntity outFundAccountFlowEntity = new FundAccountFlowEntity(corpid, nowTime, paasFormDataEntity.getCreatorId(), FundAccountFlowTypeEnum.FUND_TRANSFER_OUT.getCode(), paasFormDataEntity.getId(), Long.parseLong(outAccountStr), transferTime, -amount.doubleValue());
        FundAccountFlowEntity inFundAccountFlowEntity = new FundAccountFlowEntity(corpid, nowTime, paasFormDataEntity.getCreatorId(), FundAccountFlowTypeEnum.FUND_TRANSFER_IN.getCode(), paasFormDataEntity.getId(), Long.parseLong(inAccountStr), transferTime, amount.doubleValue());
        fundAccountFlowEntityList.add(outFundAccountFlowEntity);
        fundAccountFlowEntityList.add(inFundAccountFlowEntity);
        fundAccountFlowModel.insertBatch(fundAccountFlowEntityList);
        //更新操作-转出账户
        FundAccountEntity fundAccountEntityOut = fundAccountModel.getByIdCorpid(Long.parseLong(outAccountStr), corpid);
        fundAccountEntityOut.setAmount(new BigDecimal(BasicConstant.ZERO_DOUBLE).subtract(amount));
        //更新操作-转入账户
        FundAccountEntity fundAccountEntityIn = fundAccountModel.getByIdCorpid(Long.parseLong(inAccountStr), corpid);
        fundAccountEntityIn.setAmount(amount);
        List<FundAccountEntity> updateFundAccountList = new ArrayList<>();
        updateFundAccountList.add(fundAccountEntityOut);
        updateFundAccountList.add(fundAccountEntityIn);
        fundAccountModel.updateBatchAmount(updateFundAccountList);
    }

    /**
     * 格式化excel导入的数据
     *
     * @param importFormDataDTO
     * @param titlePojoList
     * @param rowGroupPojo
     * @param fieldAttrList
     * @return
     */
    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        // data 数据
        JSONObject dataJson = new JSONObject();
        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        // 遍历数据
        for ( FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList ) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            if ( Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType()) ) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else {
                if ( Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString()) ) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType()) ) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                }else {
                    if ( Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType()) ) {
                        formDataAddDTO.setSerialNo(cellValue.toString());
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                        importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                    } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                        importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                    } else {
                        dataJson.put(attr, cellValue);
                    }
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    /**
     * 用于批量编辑功能
     *
     * @param fundTransferEditAttrUpdateDTO
     */
    @Override
    public void batchEditAttr(FundTransferEditAttrUpdateDTO fundTransferEditAttrUpdateDTO) throws XbbException {
        try {
            List<FundTransferUpdateDTO> fundTransferUpdateList =new ArrayList<>();
            List<Long> dataIdList = fundTransferEditAttrUpdateDTO.getDataIdList();
            String corpid = fundTransferEditAttrUpdateDTO.getCorpid();
            List<String> fieldList = Arrays.asList("id", "flowStatus", FundTransferEnum.SHEET_NO.getAttr(), FundTransferEnum.getAttrConnectData(FundTransferEnum.TRANSFER_TIME));
            List<PaasFormDataEntityExt> entityList = formHelp.getFormListByIds4All(corpid, IndexTypeEnum.IDX_SAAS_FUND_TRANSFER, dataIdList, fieldList);
            if (Objects.isNull(entityList)){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(entityList.size());
            List<Long> idList = new ArrayList<>(entityList.size());
            for (PaasFormDataEntityExt entityExt : entityList) {
                Long id = entityExt.getId();
                JSONObject data = entityExt.getData();
                if (data == null) {
                    continue;
                }
                idList.add(id);
                updataItemList.add(entityExt.getSerialNo());
                FundTransferUpdateDTO updateDTO = new FundTransferUpdateDTO();
                updateDTO.setId(id);
                JSONObject updateData = ProSaveHelp.getBatchUpdateData(fundTransferEditAttrUpdateDTO.getFieldEditedList());
                updateDTO.setData(updateData);
                fundTransferUpdateList.add(updateDTO);
            }
            if (CollectionsUtil.isNotEmpty(fundTransferUpdateList)) {
                FundTransferUpdateBatchDTO updateBatchDTO = new FundTransferUpdateBatchDTO();
                BeanUtil.copyProperties(fundTransferEditAttrUpdateDTO, updateBatchDTO);
                updateBatchDTO.setUpdateList(fundTransferUpdateList);
                updateAttrBatch(updateBatchDTO);

                String updataItem = StringUtils.join(updataItemList, "，");
                String userId = fundTransferEditAttrUpdateDTO.getUserId();
                String loginUserName = fundTransferEditAttrUpdateDTO.getLoginUserName();
                // 标签特殊处理
                Integer fieldType = fundTransferEditAttrUpdateDTO.getFieldType();
                Boolean isFieldDependence = fundTransferEditAttrUpdateDTO.getIsFieldDependence();
                logHelp.analysisLabel(corpid, fieldType, isFieldDependence,fundTransferEditAttrUpdateDTO.getLogFieldEditedList());

                String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(fundTransferEditAttrUpdateDTO.getLogFieldEditedList());
                if(idList.size() > 1 ){
                    String memo = format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.FUND_TRANSFER.getName(), changedLogItemsStr, idList.size());
                    List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    InfoArrPojo infoArrPojo = new InfoArrPojo();
                    infoArrPojo.setTitle(XbbRefTypeEnum.FUND_TRANSFER.getName());
                    infoArrPojo.setContent(updataItem);
                    infoArrPojoList.add(infoArrPojo);
                    mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.FUND_TRANSFER, OperateTypeEnum.EDIT, "", "", memo, fundTransferEditAttrUpdateDTO.getHttpHeader());
                } else if (Objects.equals(idList.size(), 1)){
                    String memo = format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.FUND_TRANSFER.getName(), updataItem, changedLogItemsStr);
                    mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.FUND_TRANSFER, OperateTypeEnum.EDIT, idList.get(0).toString(), updataItem, memo, fundTransferEditAttrUpdateDTO.getHttpHeader());
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("FundTransferServiceImpl.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 格式化资金调拨单显示
     *
     * @param formDataListDTO
     * @param esEntities
     * @param totalCount
     * @return
     */
    @Override
    public ListAppVO formatFundTransferAppList(FormDataListDTO formDataListDTO, List<PaasFormDataEntityExt> esEntities, Integer totalCount) throws XbbException {
        List<AppListPojo> appListPojos = new ArrayList<>();
        for(PaasFormDataEntityExt entity : esEntities){
            Long dataId = entity.getDataId();
            JSONObject data = entity.getData();
            JSONObject superScript = new JSONObject();
            JSONObject others = new JSONObject();
            List<SummaryDataPoJo> summaryList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.SUMMARY_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<SummaryDataPoJo> lablesList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.LABELS_LIST, new JSONArray()).toJavaList(SummaryDataPoJo.class);
            List<FormTitlePoJo> titleList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, BasicConstant.TITLE_LIST, new JSONArray()).toJavaList(FormTitlePoJo.class);
            if (titleList.isEmpty()) {
                titleList.add(commonHelp.setTitle(entity.getSerialNo()));
            }

            appListPojos.add(new AppListPojo(dataId, titleList, summaryList, superScript, lablesList, others, entity.getAppId(), entity.getMenuId(), entity.getFormId()));
        }
        ListAppVO listAppVO = new ListAppVO();
        listAppVO.setList(appListPojos);
        listAppVO.setTotalCount(totalCount);
        return  listAppVO;
    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) {

    }

    @Override
    public FormDataDeleteBatchVO deleteBatch(FormDataDeleteBatchDTO formDataDeleteBatchDTO) throws XbbException {
        FormDataDeleteBatchVO formDataDeleteBatchVO = new FormDataDeleteBatchVO();
        fundTransferModel.deleteBatch(formDataDeleteBatchDTO.getDataIdList(), formDataDeleteBatchDTO.getCorpid());
        formDataDeleteBatchVO.setDeleteIds(formDataDeleteBatchDTO.getDataIdList());
        return formDataDeleteBatchVO;
    }


    /**
     * 批量更新-只更新特定字段
     *
     * @param fundTransferUpdateBatchDTO
     */
    private BaseVO updateAttrBatch(FundTransferUpdateBatchDTO fundTransferUpdateBatchDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        try {
            String corpid = fundTransferUpdateBatchDTO.getCorpid();
            List<FundTransferUpdateDTO> updateList = fundTransferUpdateBatchDTO.getUpdateList();
            if (Objects.nonNull(updateList)  && !updateList.isEmpty()) {
                List<UpdateDataEntity> list = new ArrayList<>();
                updateList.forEach((item) -> {
                    list.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                });
                if (!list.isEmpty()) {
                    fundTransferModel.updateBatch(list, corpid);
                }
            }
        } catch (Exception e) {
            LOG.error("FundTransferServiceImpl.updateBatch 批量更新出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return baseVO;
    }

}
